package com.hiernate.queryCache ;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.hibernate.domain.Classes;
import com.hibernate.utils.HibernateUtils;

public class QueryCacheTest extends HibernateUtils{

	/**
	 * 查询缓存测试01
	 * 		将数据库中查询出来的数据放入到查询缓存中
	 */
	@Test
	public void testQuery_1(){
		Session session = sessionFactory.openSession() ;
		Query query = session.createQuery("select sname from Student") ;
		//打开query对象的查询缓存
		query.setCacheable(true) ;
		//从数据库中获取查询结果，并将数据放入到查询缓存
		List list = query.list() ;
		//输出查询缓存中的实体个数	
		System.out.println(sessionFactory.getStatistics().getQueryCacheHitCount());
		//关闭当前session
		session.close() ;
		//开启一个新的session
		Session session2 = sessionFactory.openSession() ;
		Query query2 = session2.createQuery("select sname from Student") ;
		//打开query对象的查询缓存
		query2.setCacheable(true) ;
		//判断：
		/**
		 * 执行query2.list()时，判断：
		 * 	1、如果发出sql语句，说明数据是从数据库取出来的
		 * 	2、没有发出sql语句，说明数据是从查询缓存中得到的
		 */
		List list2 = query2.list() ;
		session.close() ;
	}
	
	/**
	 *  查询缓存测试02
	 *  	查询缓存中数据对应的对象信息发生改变时，清空缓存
	 */
	@Test
	public void testQuery_4(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		Query query = session.createQuery("select name from Classes");
		query.setCacheable(true);
		query.list();
		Classes classes = (Classes)session.get(Classes.class, 1L);
		classes.setDescription("aaaaaaa");
		transaction.commit();//查询缓存中数据对应的对象信息发生改变时，该对象在查询缓存中保存的数据被清除
		session.close();
		session = sessionFactory.openSession();
		query = session.createQuery("select name from Classes");
		query.setCacheable(true);
		List list = query.list();//缓存中的数据被清除，重新发出sql语句，并将查询数据再次放入到查询缓存
		session.close();
	}
	
	/**
	 * 查询缓存的命中率
	 *   命中率比较低：虽然查询缓存中有查询所需数据，但由于查询语句不一致，导致不能直接从查询缓存中取相应的数据，而是再次读取数据库进行查询
	 */
	@Test
	public void testQuery_5(){
		Session session = sessionFactory.openSession();
		Query query = session.createQuery("select name from Classes");
		query.setCacheable(true);
		query.list();
		System.out.println(sessionFactory.getStatistics().getQueryCachePutCount());
		session.close();
		session = sessionFactory.openSession();
		query = session.createQuery("select name from Classes where cid=1");
		query.setCacheable(true);
		query.list();//发出sql语句，因为两个hql语句不一样
		session.close();
	}
	
	/**
	 * 查询结果为对象/对象集合时，既要把对象放入到对象缓存中，也要放入到查询缓存中
	 * 		但是通过query.list()只能从对象缓存中取，无法从查询缓存中获取 
	 * 		不过可以通过改变查询语句来达到保存对象数据
	 * 			Query query = session.createQuery("from Classes");	//查询出来的是对象，可以放入到查询缓存，但无法获取
	 * 			Query query = session.createQuery("select * from Classes"); //查询出来的是对象数据，可以放入到查询缓存，然后从查询缓存中读取
	 */
	@Test
	public void testQuery_6(){
		Session session = sessionFactory.openSession();
		Query query = session.createQuery("from Classes");
		query.setCacheable(true);
		query.list();//既要把对象放入到对象缓存中，也要放入到查询缓存中
		System.out.println(sessionFactory.getStatistics().getQueryCachePutCount());
		session.close();
		session = sessionFactory.openSession();
		query = session.createQuery("from Classes");
		query.setCacheable(true);
		query.list();//取的时候从对象缓存中取
		session.close();
	}
}
